package us.luosl.lslt.lang;

import java.util.Objects;
import java.util.function.Function;

public class Tuple3<T1, T2, T3> implements Tuple{

    public final T1 _1;

    public final T2 _2;

    public final T3 _3;

    public Tuple3(T1 _1, T2 _2, T3 _3) {
        this._1 = _1;
        this._2 = _2;
        this._3 = _3;
    }


    public <R> Tuple3<R, T2, T3> map1(Function<T1, R> function){
        return Tuple.of(function.apply(_1), _2, _3);
    }

    public <R> Tuple3<T1, R, T3> map2(Function<T2, R> function){
        return Tuple.of(_1, function.apply(_2), _3);
    }

    public <R> Tuple3<T1, T2, R> map3(Function<T3, R> function){
        return Tuple.of(_1, _2, function.apply(_3));
    }

    public Tuple3<T3, T2, T1> reverse(){
        return Tuple.of(_3, _2, _1);
    }

    @Override
    public int hashCode() {
        int result = 1;
        result = 31 * result + Objects.hashCode(_1);
        result = 31 * result + Objects.hashCode(_2);
        result = 31 * result + Objects.hashCode(_3);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        } else if (!(obj instanceof Tuple3)) {
            return false;
        } else {
            final Tuple3<?, ?, ?> that = (Tuple3<?, ?, ?>) obj;
            return Objects.equals(this._1, that._1)
                    && Objects.equals(this._2, that._2)
                    && Objects.equals(this._3, that._3);
        }
    }
}
